package com.zkq.lvse.common.dao.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.zkq.lvse.common.dao.BaseDao;
import com.zkq.lvse.common.utils.Page;

@SuppressWarnings("unchecked")
@Repository
public class BaseDaoImpl<T,PK extends Serializable> extends SimpleDaoImpl<T, PK> implements BaseDao<T, PK> {
	
	public BaseDaoImpl(){
	}
	public BaseDaoImpl(final SessionFactory sessionFactory,final Class<T> entityClass){
		super(sessionFactory,entityClass);
	}
	
	/**
	 * 为Query设置分页参数
	 * @param q
	 * @param page
	 * @return
	 */
	public Query setParamterPageToQuery(final Query q,final Page<T> page){
		q.setFirstResult((int) ((page.getPageNo()-1)*page.getPageSize()));
		q.setMaxResults((int)page.getPageSize());
		return q;
	}
	/**
	 * 为SQLQuery设置分页参数
	 * @param sq
	 * @param page	分页参数
	 * @return
	 */
	public SQLQuery setParamterPageToSQLQuery(final SQLQuery sq,final Page<T> page){
		sq.setFirstResult((int)((page.getPageNo()-1)*page.getPageSize()));
		sq.setMaxResults((int)page.getPageSize());
		return sq;
	}
	/**
	 * 为Criteria设置分页参数
	 * @param c
	 * @param page	分页参数
	 * @return
	 */
	public Criteria setParamterPageToCriteria(final Criteria c,final Page<T> page){
		c.setFirstResult((int)((page.getPageNo()-1)*page.getPageSize()));
		c.setMaxResults((int)page.getPageSize());
		return c;
	}
	
	/**
	 * 根据HQL分页查询对象列表
	 * @param page	分页参数
	 * @param hql	HQL
	 * @param values	数量可变参数，按顺序绑定
	 * @return
	 */
	public Page<T> findPage(Page<T> page, String hql, Object... values) {
		Query q=null;
		if(values!=null){
			q=createQuery(hql, values);
		}else{
			q=createQuery(hql);
		}
		long totalCount=count(hql, values);
		long totalPages=totalCount%page.getPageSize()==0?totalCount/page.getPageSize():totalCount/page.getPageSize()+1;
		page.setTotalPages(totalPages);
		page.setTotalCount(totalCount);
		setParamterPageToQuery(q, page);
		List<T> list=q.list();
		page.setList(list);
		return page;
	}
	/**
	 * 根据HQL分页查询对象列表
	 * @param page	分页参数
	 * @param hql	HQL
	 * @param values	数量可变参数，按名称绑定
	 * @return
	 */
	public Page<T> findPage(Page<T> page, String hql, Map<String, ?> values) {
		Query q=null;
		if(values!=null){
			q=createQuery(hql, values);
		}else{
			q=createQuery(hql);
		}
		long totalCount=count(hql, values);
		long totalPages=totalCount%page.getPageSize()==0?totalCount/page.getPageSize():totalCount/page.getPageSize()+1;
		page.setTotalPages(totalPages);
		page.setTotalCount(totalCount);
		setParamterPageToQuery(q, page);
		List<T> list=q.list();
		page.setList(list);
		return page;
	}
	/**
	 * 根据Criteria分页查询对象列表
	 * @param page	分页参数
	 * @param criterions	数量可变Criterion参数，按顺序绑定
	 * @return
	 */
	public Page<T> findPage(Page<T> page, Criterion... criterions) {
		Criteria c=createCriteria(criterions);
		countCriteria(c, page);
		setParamterPageToCriteria(c, page);
		List<T> list=c.list();
		page.setList(list);
		return page;
	}
	/**
	 * 根据Criteria查询对象总数
	 * @param c
	 * @return
	 */
	public Criteria countCriteria(Criteria c,Page<T> page){
		c.setProjection(Projections.rowCount());
		Long cou=(Long) c.uniqueResult();
		long totalPages=cou%page.getPageSize()==0?cou/page.getPageSize():cou/page.getPageSize()+1;
		page.setTotalPages(totalPages);
		page.setTotalCount(cou);
		c.setProjection(null);
		return c;
	}
	/**
	 * 根据ID列表分页查询对象列表
	 * @param page	分页参数
	 * @param ids	ID列表
	 * @return
	 */
	public Page<T> findPage(Page<T> page, Collection<PK> ids) {
		Criterion co=Restrictions.in(getIdName(), ids);
		Criteria c=createCriteria(co);
		countCriteria(c, page);
		setParamterPageToCriteria(c, page);
		List<T> list=c.list();
		page.setList(list);
		return page;
	}
	/**
	 * 根据SQL语句分页查询对象列表
	 * @param page	分页参数
	 * @param sql	sql语句
	 * @param clz	实体类class
	 * @return
	 */
	public Page<T> findPage(Page<T> page, String sql, Class<T> clz) {
		SQLQuery sq=createSqlQuery(sql).addEntity(clz);
		//查询总数
		setPageCount(sq, page);
		//为SQLQuery设置分页参数
		setParamterPageToSQLQuery(sq, page);
		List<T> list=sq.list();
		page.setList(list);
		return page;
	}
	
	public void setPageCount(SQLQuery sq,Page<T> page){
		long size=sq.list().size();
		page.setTotalCount(size);
		long totalPages=size%page.getPageSize()==0?size/page.getPageSize():size/page.getPageSize()+1;
		page.setTotalPages(totalPages);
	}
	/**
	 * 根据SQL语句分页查询对象列表
	 * @param page	分页参数
	 * @param sql	sql语句
	 * @param clz	实体类class
	 * @param vlaues	数量可变参数，按顺序绑定
	 * @return
	 */
	public Page<T> findPage(Page<T> page, String sql, Class<T> clz,Object... values) {
		SQLQuery sq=createSqlQuery(sql,values).addEntity(clz);
		//查询总数
		setPageCount(sq, page);
		//为SQLQuery设置分页参数
		setParamterPageToSQLQuery(sq, page);
		List<T> list=sq.list();
		page.setList(list);
		return page;
	}
	/**
	 * 分页查询全部对象列表
	 * @param page
	 * @return
	 */
	public Page<T> getAll(Page<T> page) {
		return findPage(page);
	}
	public long count(String hql, Object... values) {
		Query q=createQuery(hql, values);
		long count=q.list().size();
		return count;
	}

}
